public class Spiral {
	public static void main (String args[]) {
		Spiral gen = new Spiral();
		//make some spirals
		final int[][] one = gen.spiral(1);
		final int[][] three = gen.spiral(3);
		final int[][] five = gen.spiral(5);
		final int[][] eleven = gen.spiral(11);
		//check that all went well
		assert one.length == 1;
		assert one[0].length == 1;
		assert one[0][0] == 1;
		assert three.length == 3;
		assert three[0].length == 3;
		assert three[0][2] == 9;
		assert three[0][1] == 8;
		assert three[0][0] == 7;
		assert three[1][0] == 6;
		assert three[2][0] == 5;
		assert three[2][1] == 4;
		assert three[2][2] == 3;
		assert three[1][2] == 2;
		assert three[1][1] == 1;
		//print the spirals
		gen.printSpiral(one);
		gen.printSpiral(three);
		gen.printSpiral(five);
		gen.printSpiral(eleven);
	}

	public int[][] spiral (final int side) {
		final int[][] ret = new int[side][side];
		ret[0][side - 1] = side * side;
		spiral_(ret, 0, side - 1, side * side - 1, Direction.left);
		return ret;
	}

	private void spiral_(final int[][] box, final int row, final int col, final int num, final Direction d) {
		switch(d) {
			case left:
				if (col - 1 >= 0 && box[row][col - 1] == 0) { //if we can continue
					box[row][col - 1] = num;
					spiral_(box, row, col - 1, num - 1, Direction.left);
					break;
				} //otherwise fall through to down
			case down:
				if (row + 1 < box.length && box[row + 1][col] == 0) { //if we can continue
					box[row + 1][col] = num;
					spiral_(box, row + 1, col, num - 1, Direction.down);
					break;
				} //otherwise fall through to right
			case right:
				if (col + 1 < box.length && box[row][col + 1] == 0) { //if we can continue
					box[row][col + 1] = num;
					spiral_(box, row, col + 1, num - 1, Direction.right);
					break;
				} //otherwise fall through to up
			case up:
				if (row - 1 >= 0 && box[row - 1][col] == 0) { //if we can continue
					box[row - 1][col] = num;
					spiral_(box, row - 1, col, num - 1, Direction.up);
					break;
				} //otherwise fall through to default
			default:
				//try to go left again
				if (col - 1 >= 0 && box[row][col - 1] == 0) { //if we can continue
					box[row][col - 1] = num;
					spiral_(box, row, col - 1, num - 1, Direction.left);
					break;
				}
				//if that doesn't work we're done
		}
	}

	private void printSpiral(final int[][] box) {
		System.out.println(box.length + " spiral:");
		for (int[] row : box) {
			for (int num : row) {
				System.out.print(num + "\t");
			}
			System.out.println();
		}
		System.out.println();
	}

	enum Direction {
		left,
		right,
		up,
		down;
	}
}

